home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / automake-1.8 / Automake / Condition.pm < prev    next >
Encoding:
Perl POD Document  |  2005-10-16  |  15.3 KB  |  651 lines

  1. # Copyright (C) 1997, 2001, 2002, 2003  Free Software Foundation, Inc.
  2.  
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2, or (at your option)
  6. # any later version.
  7.  
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12.  
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  16. # 02111-1307, USA.
  17.  
  18. package Automake::Condition;
  19. use strict;
  20. use Carp;
  21.  
  22. require Exporter;
  23. use vars '@ISA', '@EXPORT_OK';
  24. @ISA = qw/Exporter/;
  25. @EXPORT_OK = qw/TRUE FALSE reduce_and reduce_or/;
  26.  
  27. =head1 NAME
  28.  
  29. Automake::Condition - record a conjunction of conditionals
  30.  
  31. =head1 SYNOPSIS
  32.  
  33.   use Automake::Condition;
  34.  
  35.   # Create a condition to represent "COND1 and not COND2".
  36.   my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
  37.   # Create a condition to represent "not COND3".
  38.   my $other = new Automake::Condition "COND3_FALSE";
  39.  
  40.   # Create a condition to represent
  41.   #   "COND1 and not COND2 and not COND3".
  42.   my $both = $cond->merge ($other);
  43.  
  44.   # Likewise, but using a list of conditional strings
  45.   my $both2 = $cond->merge_conds ("COND3_FALSE");
  46.  
  47.   # Strip from $both any subconditions which are in $other.
  48.   # This is the opposite of merge.
  49.   $cond = $both->strip ($other);
  50.  
  51.   # Return the list of conditions ("COND1_TRUE", "COND2_FALSE"):
  52.   my @conds = $cond->conds;
  53.  
  54.   # Is $cond always true?  (Not in this example)
  55.   if ($cond->true) { ... }
  56.  
  57.   # Is $cond always false? (Not in this example)
  58.   if ($cond->false) { ... }
  59.  
  60.   # Return the list of conditionals as a string:
  61.   #  "COND1_TRUE COND2_FALSE"
  62.   my $str = $cond->string;
  63.  
  64.   # Return the list of conditionals as a human readable string:
  65.   #  "COND1 and !COND2"
  66.   my $str = $cond->human;
  67.  
  68.   # Return the list of conditionals as a AC_SUBST-style string:
  69.   #  "@COND1_TRUE@@COND2_FALSE@"
  70.   my $subst = $cond->subst_string;
  71.  
  72.   # Is $cond true when $both is true?  (Yes in this example)
  73.   if ($cond->true_when ($both)) { ... }
  74.  
  75.   # Is $cond redundant w.r.t. {$other, $both}?
  76.   # (Yes in this example)
  77.   if ($cond->redundant_wrt ($other, $both)) { ... }
  78.  
  79.   # Does $cond imply any of {$other, $both}?
  80.   # (Not in this example)
  81.   if ($cond->implies_any ($other, $both)) { ... }
  82.  
  83.   # Remove superfluous conditionals assuming they will eventually
  84.   # be multiplied together.
  85.   # (Returns @conds = ($both) in this example, because
  86.   # $other and $cond are implied by $both.)
  87.   @conds = Automake::Condition::reduce_and ($other, $both, $cond);
  88.  
  89.   # Remove superfluous conditionals assuming they will eventually
  90.   # be summed together.
  91.   # (Returns @conds = ($cond, $other) in this example, because
  92.   # $both is a subset condition of $cond: $cond is true whenever $both
  93.   # is true.)
  94.   @conds = Automake::Condition::reduce_or ($other, $both, $cond);
  95.  
  96.   # Invert a Condition.  This returns a list of Conditions.
  97.   @conds = $both->not;
  98.  
  99. =head1 DESCRIPTION
  100.  
  101. A C<Condition> is a conjunction of conditionals (i.e., atomic conditions
  102. defined in F<configure.ac> by C<AM_CONDITIONAL>.  In Automake they
  103. are used to represent the conditions into which F<Makefile> variables and
  104. F<Makefile> rules are defined.
  105.  
  106. If the variable C<VAR> is defined as
  107.  
  108.   if COND1
  109.     if COND2
  110.       VAR = value
  111.     endif
  112.   endif
  113.  
  114. then it will be associated a C<Condition> created with
  115. the following statement.
  116.  
  117.   new Automake::Condition "COND1_TRUE", "COND2_TRUE";
  118.  
  119. Remember that a C<Condition> is a I<conjunction> of conditionals, so
  120. the above C<Condition> means C<VAR> is defined when C<COND1>
  121. B<and> C<COND2> are true. There is no way to express disjunctions
  122. (i.e., I<or>s) with this class (but see L<DisjConditions>).
  123.  
  124. Another point worth to mention is that each C<Condition> object is
  125. unique with respect to its conditionals.  Two C<Condition> objects
  126. created for the same set of conditionals will have the same adress.
  127. This makes it easy to compare C<Condition>s, just compare the
  128. references.
  129.  
  130.   my $c1 = new Automake::Condition "COND1_TRUE", "COND2_TRUE";
  131.   my $c2 = new Automake::Condition "COND1_TRUE", "COND2_TRUE";
  132.   $c1 == $c2;  # True!
  133.  
  134. =head2 Methods
  135.  
  136. =over 4
  137.  
  138. =item C<$cond = new Automake::Condition [@conds]>
  139.  
  140. Return a C<Condition> objects for the conjunctions of conditionals
  141. listed in C<@conds> as strings.
  142.  
  143. An item in C<@conds> should be either C<"FALSE">, C<"TRUE">, or have
  144. the form C<"NAME_FALSE"> or C<"NAME_TRUE"> where C<NAME> can be
  145. anything (in practice C<NAME> should be the name of a conditional
  146. declared in F<configure.ac> with C<AM_CONDITIONAL>, but it's not
  147. C<Automake::Condition>'s responsability to ensure this).
  148.  
  149. An empty C<@conds> means C<"TRUE">.
  150.  
  151. As explained previously, the reference (object) returned is unique
  152. with respect to C<@conds>.  For this purpose, duplicate elements are
  153. ignored, and C<@conds> is rewriten as C<("FALSE")> if it contains
  154. C<"FALSE"> or two contradictory conditionals (such as C<"NAME_FALSE">
  155. and C<"NAME_TRUE">.)
  156.  
  157. Therefore the following two statements create the same object (they
  158. both create the C<"FALSE"> condition).
  159.  
  160.   my $c3 = new Automake::Condition "COND1_TRUE", "COND1_FALSE";
  161.   my $c4 = new Automake::Condition "COND2_TRUE", "FALSE";
  162.   $c3 == $c4;   # True!
  163.   $c3 == FALSE; # True!
  164.  
  165. =cut
  166.  
  167. # Keys in this hash are conditional strings. Values are the
  168. # associated object conditions.  This is used by `new' to reuse
  169. # Condition objects with identical conditionals.
  170. use vars '%_condition_singletons';
  171. # Do NOT reset this hash here.  It's already empty by default,
  172. # and any setting would otherwise occur AFTER the `TRUE' and `FALSE'
  173. # constants definitions.
  174. #   %_condition_singletons = ();
  175.  
  176. sub new ($;@)
  177. {
  178.   my ($class, @conds) = @_;
  179.   my $self = {
  180.     hash => {},
  181.   };
  182.   bless $self, $class;
  183.  
  184.   # Accept strings like "FOO BAR" as shorthand for ("FOO", "BAR").
  185.   @conds = map { split (' ', $_) } @conds;
  186.  
  187.   for my $cond (@conds)
  188.     {
  189.       next if $cond eq 'TRUE';
  190.  
  191.       # Catch some common programming errors:
  192.       # - A Condition passed to new
  193.       confess "`$cond' is a reference, expected a string" if ref $cond;
  194.       # - A Condition passed as a string to new
  195.       confess "`$cond' does not look like a condition" if $cond =~ /::/;
  196.  
  197.       # Detect cases when @conds can be simplified to FALSE.
  198.       if (($cond eq 'FALSE' && $#conds > 0)
  199.       || ($cond =~ /^(.*)_TRUE$/ && exists $self->{'hash'}{"${1}_FALSE"})
  200.       || ($cond =~ /^(.*)_FALSE$/ && exists $self->{'hash'}{"${1}_TRUE"}))
  201.     {
  202.       return &FALSE;
  203.     }
  204.  
  205.       $self->{'hash'}{$cond} = 1;
  206.     }
  207.  
  208.   my $key = $self->string;
  209.   if (exists $_condition_singletons{$key})
  210.     {
  211.       return $_condition_singletons{$key};
  212.     }
  213.   $_condition_singletons{$key} = $self;
  214.   return $self;
  215. }
  216.  
  217. =item C<$newcond = $cond-E<gt>merge (@otherconds)>
  218.  
  219. Return a new condition which is the conjunction of
  220. C<$cond> and C<@otherconds>.
  221.  
  222. =cut
  223.  
  224. sub merge ($@)
  225. {
  226.   my ($self, @otherconds) = @_;
  227.   new Automake::Condition (map { $_->conds } ($self, @otherconds));
  228. }
  229.  
  230. =item C<$newcond = $cond-E<gt>merge_conds (@conds)>
  231.  
  232. Return a new condition which is the conjunction of C<$cond> and
  233. C<@conds>, where C<@conds> is a list of conditional strings, as
  234. passed to C<new>.
  235.  
  236. =cut
  237.  
  238. sub merge_conds ($@)
  239. {
  240.   my ($self, @conds) = @_;
  241.   new Automake::Condition $self->conds, @conds;
  242. }
  243.  
  244. =item C<$newcond = $cond-E<gt>strip ($minuscond)>
  245.  
  246. Return a new condition which has all the conditionals of C<$cond>
  247. except those of C<$minuscond>.  This is the opposite of C<merge>.
  248.  
  249. =cut
  250.  
  251. sub strip ($$)
  252. {
  253.   my ($self, $minus) = @_;
  254.   my @res = grep { not $minus->has ($_) } $self->conds;
  255.   return new Automake::Condition @res;
  256. }
  257.  
  258. =item C<@list = $cond-E<gt>conds>
  259.  
  260. Return the set of conditionals defining C<$cond>, as strings.  Note that
  261. this might not be exactly the list passed to C<new> (or a
  262. concatenation of such lists if C<merge> was used), because of the
  263. cleanup mentioned in C<new>'s description.
  264.  
  265. For instance C<$c3-E<gt>conds> will simply return C<("FALSE")>.
  266.  
  267. =cut
  268.  
  269. sub conds ($ )
  270. {
  271.   my ($self) = @_;
  272.   my @conds = keys %{$self->{'hash'}};
  273.   return ("TRUE") unless @conds;
  274.   return sort @conds;
  275. }
  276.  
  277. # Undocumented, shouldn't be needed out of this class.
  278. sub has ($$)
  279. {
  280.   my ($self, $cond) = @_;
  281.   return exists $self->{'hash'}{$cond};
  282. }
  283.  
  284. =item C<$cond-E<gt>false>
  285.  
  286. Return 1 iff this condition is always false.
  287.  
  288. =cut
  289.  
  290. sub false ($ )
  291. {
  292.   my ($self) = @_;
  293.   return $self->has ('FALSE');
  294. }
  295.  
  296. =item C<$cond-E<gt>true>
  297.  
  298. Return 1 iff this condition is always true.
  299.  
  300. =cut
  301.  
  302. sub true ($ )
  303. {
  304.   my ($self) = @_;
  305.   return 0 == keys %{$self->{'hash'}};
  306. }
  307.  
  308. =item C<$cond-E<gt>string>
  309.  
  310. Build a string which denotes the condition.
  311.  
  312. For instance using the C<$cond> definition from L<SYNOPSYS>,
  313. C<$cond-E<gt>string> will return C<"COND1_TRUE COND2_FALSE">.
  314.  
  315. =cut
  316.  
  317. sub string ($ )
  318. {
  319.   my ($self) = @_;
  320.  
  321.   return $self->{'string'} if defined $self->{'string'};
  322.  
  323.   my $res = '';
  324.   if ($self->false)
  325.     {
  326.       $res = 'FALSE';
  327.     }
  328.   else
  329.     {
  330.       $res = join (' ', $self->conds);
  331.     }
  332.   $self->{'string'} = $res;
  333.   return $res;
  334. }
  335.  
  336. =item C<$cond-E<gt>human>
  337.  
  338. Build a human readable string which denotes the condition.
  339.  
  340. For instance using the C<$cond> definition from L<SYNOPSYS>,
  341. C<$cond-E<gt>string> will return C<"COND1 and !COND2">.
  342.  
  343. =cut
  344.  
  345. sub _to_human ($ )
  346. {
  347.   my ($s) = @_;
  348.   if ($s =~ /^(.*)_(TRUE|FALSE)$/)
  349.     {
  350.       return (($2 eq 'FALSE') ? '!' : '') . $1;
  351.     }
  352.   else
  353.     {
  354.       return $s;
  355.     }
  356. }
  357.  
  358. sub human ($ )
  359. {
  360.   my ($self) = @_;
  361.  
  362.   return $self->{'human'} if defined $self->{'human'};
  363.  
  364.   my $res = '';
  365.   if ($self->false)
  366.     {
  367.       $res = 'FALSE';
  368.     }
  369.   else
  370.     {
  371.       $res = join (' and ', map { _to_human $_ } $self->conds);
  372.     }
  373.   $self->{'human'} = $res;
  374.   return $res;
  375. }
  376.  
  377. =item C<$cond-E<gt>subst_string>
  378.  
  379. Build a C<AC_SUBST>-style string for output in F<Makefile.in>.
  380.  
  381. For instance using the C<$cond> definition from L<SYNOPSYS>,
  382. C<$cond-E<gt>subst_string> will return C<"@COND1_TRUE@@COND2_FALSE@">.
  383.  
  384. =cut
  385.  
  386. sub subst_string ($ )
  387. {
  388.   my ($self) = @_;
  389.  
  390.   return $self->{'subst_string'} if defined $self->{'subst_string'};
  391.  
  392.   my $res = '';
  393.   if ($self->false)
  394.     {
  395.       $res = '#';
  396.     }
  397.   elsif (! $self->true)
  398.     {
  399.       $res = '@' . join ('@@', sort $self->conds) . '@';
  400.     }
  401.   $self->{'subst_string'} = $res;
  402.   return $res;
  403. }
  404.  
  405. =item C<$cond-E<gt>true_when ($when)>
  406.  
  407. Return 1 iff C<$cond> is true when C<$when> is true.
  408. Return 0 otherwise.
  409.  
  410. Using the definitions from L<SYNOPSYS>, C<$cond> is true
  411. when C<$both> is true, but the converse is wrong.
  412.  
  413. =cut
  414.  
  415. sub true_when ($$)
  416. {
  417.   my ($self, $when) = @_;
  418.  
  419.   # Nothing is true when FALSE (not even FALSE itself, but it
  420.   # shouldn't hurt if you decide to change that).
  421.   return 0 if $self->false || $when->false;
  422.  
  423.   # If we are true, we stay true when $when is true :)
  424.   return 1 if $self->true;
  425.  
  426.   # $SELF is true under $WHEN if each conditional component of $SELF
  427.   # exists in $WHEN.
  428.   foreach my $cond ($self->conds)
  429.     {
  430.       return 0 unless $when->has ($cond);
  431.     }
  432.   return 1;
  433. }
  434.  
  435. =item C<$cond-E<gt>redundant_wrt (@conds)>
  436.  
  437. Return 1 iff C<$cond> is true for any condition in C<@conds>.
  438. If @conds is empty, return 1 iff C<$cond> is C<FALSE>.
  439. Return 0 otherwise.
  440.  
  441. =cut
  442.  
  443. sub redundant_wrt ($@)
  444. {
  445.   my ($self, @conds) = @_;
  446.  
  447.   foreach my $cond (@conds)
  448.     {
  449.       return 1 if $self->true_when ($cond);
  450.     }
  451.   return $self->false;
  452. }
  453.  
  454. =item C<$cond-E<gt>implies_any (@conds)>
  455.  
  456. Return 1 iff C<$cond> implies any of the conditions in C<@conds>.
  457. Return 0 otherwise.
  458.  
  459. =cut
  460.  
  461. sub implies_any ($@)
  462. {
  463.   my ($self, @conds) = @_;
  464.  
  465.   foreach my $cond (@conds)
  466.     {
  467.       return 1 if $cond->true_when ($self);
  468.     }
  469.   return 0;
  470. }
  471.  
  472. =item C<$cond-E<gt>not>
  473.  
  474. Return a negation of C<$cond> as a list of C<Condition>s.
  475. This list should be used to construct a C<DisjConditions>
  476. (we cannot return a C<DisjConditions> from C<Automake::Condition>,
  477. because that would make these two packages interdependent).
  478.  
  479. =cut
  480.  
  481. sub not ($ )
  482. {
  483.   my ($self) = @_;
  484.   return @{$self->{'not'}} if defined $self->{'not'};
  485.   my @res =
  486.     map { new Automake::Condition &conditional_negate ($_) } $self->conds;
  487.   $self->{'not'} = [@res];
  488.   return @res;
  489. }
  490.  
  491. =item C<$cond-E<gt>multiply (@conds)>
  492.  
  493. Assumption: C<@conds> represent a disjunction of conditions.
  494.  
  495. Return the result of multiplying C<$cond> with that disjunction.
  496. The result will be a list of conditions suitable to construct a
  497. C<DisjConditions>.
  498.  
  499. =cut
  500.  
  501. sub multiply ($@)
  502. {
  503.   my ($self, @set) = @_;
  504.   my %res = ();
  505.   for my $cond (@set)
  506.     {
  507.       my $ans = $self->merge ($cond);
  508.       $res{$ans} = $ans;
  509.     }
  510.  
  511.   # FALSE can always be removed from a disjunction.
  512.   delete $res{FALSE};
  513.  
  514.   # Now, $self is a common factor of the remaining conditions.
  515.   # If one of the conditions is $self, we can discard the rest.
  516.   return ($self, ())
  517.     if exists $res{$self};
  518.  
  519.   return (values %res);
  520. }
  521.  
  522. =head2 Other helper functions
  523.  
  524. =over 4
  525.  
  526. =item C<TRUE>
  527.  
  528. The C<"TRUE"> conditional.
  529.  
  530. =item C<FALSE>
  531.  
  532. The C<"FALSE"> conditional.
  533.  
  534. =cut
  535.  
  536. use constant TRUE => new Automake::Condition "TRUE";
  537. use constant FALSE => new Automake::Condition "FALSE";
  538.  
  539. =item C<reduce_and (@conds)>
  540.  
  541. Return a subset of @conds with the property that the conjunction of
  542. the subset is the same as the conjunction of @conds.  For example, if
  543. both C<COND1_TRUE COND2_TRUE> and C<COND1_TRUE> are in the list,
  544. discard the latter.  If the input list is empty, return C<(TRUE)>.
  545.  
  546. =cut
  547.  
  548. sub reduce_and (@)
  549. {
  550.   my (@conds) = @_;
  551.   my @ret = ();
  552.   my $cond;
  553.   while (@conds > 0)
  554.     {
  555.       $cond = shift @conds;
  556.  
  557.       # FALSE is absorbent.
  558.       return FALSE
  559.     if $cond == FALSE;
  560.  
  561.       if (! $cond->redundant_wrt (@ret, @conds))
  562.     {
  563.       push (@ret, $cond);
  564.     }
  565.     }
  566.  
  567.   return TRUE if @ret == 0;
  568.   return @ret;
  569. }
  570.  
  571. =item C<reduce_or (@conds)>
  572.  
  573. Return a subset of @conds with the property that the disjunction of
  574. the subset is equivalent to the disjunction of @conds.  For example,
  575. if both C<COND1_TRUE COND2_TRUE> and C<COND1_TRUE> are in the list,
  576. discard the former.  If the input list is empty, return C<(FALSE)>.
  577.  
  578. =cut
  579.  
  580. sub reduce_or (@)
  581. {
  582.   my (@conds) = @_;
  583.   my @ret = ();
  584.   my $cond;
  585.   while (@conds > 0)
  586.     {
  587.       $cond = shift @conds;
  588.  
  589.       next
  590.        if $cond == FALSE;
  591.       return TRUE
  592.        if $cond == TRUE;
  593.  
  594.       push (@ret, $cond)
  595.        unless $cond->implies_any (@ret, @conds);
  596.     }
  597.  
  598.   return FALSE if @ret == 0;
  599.   return @ret;
  600. }
  601.  
  602. =item C<conditional_negate ($condstr)>
  603.  
  604. Negate a conditional string.
  605.  
  606. =cut
  607.  
  608. sub conditional_negate ($)
  609. {
  610.   my ($cond) = @_;
  611.  
  612.   $cond =~ s/TRUE$/TRUEO/;
  613.   $cond =~ s/FALSE$/TRUE/;
  614.   $cond =~ s/TRUEO$/FALSE/;
  615.  
  616.   return $cond;
  617. }
  618.  
  619. =head1 SEE ALSO
  620.  
  621. L<Automake::DisjConditions>.
  622.  
  623. =head1 HISTORY
  624.  
  625. C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
  626. Ian Lance Taylor <ian@cygnus.org> in 1997.  Since then it has been
  627. improved by Tom Tromey <tromey@redhat.com>, Richard Boulton
  628. <richard@tartarus.org>, Raja R Harinath <harinath@cs.umn.edu>,
  629. Akim Demaille <akim@epita.fr>, and  Alexandre Duret-Lutz <adl@gnu.org>.
  630.  
  631. =cut
  632.  
  633. 1;
  634.  
  635. ### Setup "GNU" style for perl-mode and cperl-mode.
  636. ## Local Variables:
  637. ## perl-indent-level: 2
  638. ## perl-continued-statement-offset: 2
  639. ## perl-continued-brace-offset: 0
  640. ## perl-brace-offset: 0
  641. ## perl-brace-imaginary-offset: 0
  642. ## perl-label-offset: -2
  643. ## cperl-indent-level: 2
  644. ## cperl-brace-offset: 0
  645. ## cperl-continued-brace-offset: 0
  646. ## cperl-label-offset: -2
  647. ## cperl-extra-newline-before-brace: t
  648. ## cperl-merge-trailing-else: nil
  649. ## cperl-continued-statement-offset: 2
  650. ## End:
  651.